package cn.lblbc.lib.download

import android.annotation.SuppressLint
import android.content.Context
import cn.lblbc.lib.download.DownloadError.DEFAULT_ERROR
import cn.lblbc.lib.download.DownloadError.UNKNOWN_HTTP_CODE
import cn.lblbc.lib.download.db.AppDatabase
import cn.lblbc.lib.download.db.bean.DbDownloadTaskInfo
import cn.lblbc.lib.download.db.dao.DownloadDao
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.ExecutorService
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit

@SuppressLint("StaticFieldLeak")
object FileDownloadManager {
    private val tag = "FileDownloadManager"
    private lateinit var downloadDao: DownloadDao
    private var downloadRequestMap = HashMap<String, DownloadRequest>()
    private lateinit var mContext: Context

    private var executorService: ExecutorService = ThreadPoolExecutor(
        MAX_RUNNING_TASK_COUNT, MAX_RUNNING_TASK_COUNT,
        0, TimeUnit.SECONDS,
        ArrayBlockingQueue(512),  // 使用有界队列，避免OOM
        ThreadPoolExecutor.DiscardPolicy()
    )

    fun init(context: Context) {
        mContext = context
        downloadDao = AppDatabase.getInstance(context).downloadDao
    }

    fun createDownloadTask(url: String, downloadDir: String): FileDownloadTask {
        var taskId = md5(url)
        val fileName = generateDownloadApkName()
        return FileDownloadTask(taskId, url, fileName, downloadDir)
    }

    fun download(fileDownloadTask: FileDownloadTask, fileDownloadListener: FileDownloadListener): String {
        val taskId = fileDownloadTask.id
        val url = fileDownloadTask.url
        val fileName = fileDownloadTask.fileName
        val downloadFilePath = fileDownloadTask.getFilePath()

        executorService.submit {
            val downloadRequest = DownloadRequest(mContext, url, taskId, fileName, downloadFilePath, fileDownloadListener)
            downloadRequestMap[taskId] = downloadRequest
            try {
                downloadRequest.download()
            } catch (e: DownloadException) {
                fileDownloadListener.onError(e.code, e.httpCode, e.msg)
            } catch (e: Exception) {
                fileDownloadListener.onError(DEFAULT_ERROR, UNKNOWN_HTTP_CODE, e.message ?: "")
            }
        }
        return taskId
    }

    fun pauseDownload(taskId: String) {
        downloadRequestMap[taskId]?.cancel()
    }

    private fun queryTasks(): List<DbDownloadTaskInfo>? {
        return downloadDao.query()
    }
}


